package com.smartmail.view;

import com.smartmail.R;
import com.smartmail.activity.SmartMailActivity.AccountAdapter;
import com.smartmail.dragandrop.DragFrame;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;

public class NewAccountGridView extends GridView {

	public NewAccountGridView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
		setGridView();
	}

	public NewAccountGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		setGridView();
	}

	public NewAccountGridView(Context context) {
		super(context);
		this.context = context;
		setGridView();
	}
	
	public int getSpacer(){
		return spacer;
	}
	
	public int getAccountHeight(){
		return accountHeight;
	}
	
	public int getAccountWidth(){
		return accountWidth;
	}
	
	public int getItemPosition(){
		return itemToMovePosition;
	}
	
	public boolean getMoveFlag(){
		return inMoveFlag;
	}
	
	public void setDragController(DragFrame dc){
		dragController = dc;
	}
	
	/**
	 * After MotionEvent UP it is necessary to disable fade on moved account
	 */
	public void disableFader(){
		View view = this.getChildAt(itemToMovePosition);

		View viewFader = view.findViewById(R.id.accountFaderView);
		viewFader.setVisibility(View.INVISIBLE);
	}
	
	/**
	 * Function use to determine if center of dragged image is above
	 * one of accounts/empty spaces or above button.
	 * If it is above account/empty space it colorize it.
	 * 
	 * @param x - horizontal position of center of dragged image
	 * @param y - vertical position of center of dragged image
	 * @return if place was account or button
	 */
	public boolean colorizePotencialDrop(int x, int y){
		
		currPosition = this.getPositionFromOffset(x, y, getFirstVisiblePosition());
		if (currPosition < this.getChildCount()){
			View view = this.getChildAt(currPosition);
			view.findViewById(R.id.accountDropSelectorView).setVisibility(View.VISIBLE);
			if (currPosition != oldPosition){
				View v = this.getChildAt(oldPosition);
				v.findViewById(R.id.accountDropSelectorView).setVisibility(View.INVISIBLE);
				oldPosition = currPosition;
			}	
			return true;
		}
		View v = this.getChildAt(oldPosition);
		v.findViewById(R.id.accountDropSelectorView).setVisibility(View.INVISIBLE);
		return false;
	}
	
	/**
	 * After Up motion it is needed to make all boxes default
	 */
	public void uncolorizePotencialDrop(){
		View v = this.getChildAt(oldPosition);
		v.findViewById(R.id.accountDropSelectorView).setVisibility(View.INVISIBLE);		
	}

	/**
	 * Set OnItemLongClickListener - for moving accounts Set OnItemClickListener
	 * - for getting into account messages Set OnScrollListener - for change
	 * status of scrolling Set all default values
	 */
	private void setGridView() {
		inMoveFlag = false;
		wasScrolled = false;

		// -----------------------------------------------------------------
		
		this.setLongClickable(true);
		
		/*
		 * After long click, event is not consumed by PlaceHolder, it is passed
		 * here to get position of clicked item, from which it is possible
		 * to get offset and put "screenshot" of view in correct place.
		 * This listener consumes the event.
		 */
		this.setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View view,
					int position, long id) {
				int topVisiblePosition = arg0.getFirstVisiblePosition();
				firstTopPosition = topVisiblePosition;
				itemToMovePosition = position - topVisiblePosition;
				inMoveFlag = true;

				/*
				 * Setting old and current positions to clicked position
				 * in case user does not move view 
				 */
				oldPosition = itemToMovePosition;
				currPosition = itemToMovePosition;
				
				View viewFader = view.findViewById(R.id.accountFaderView);
				viewFader.setVisibility(View.VISIBLE);
				
				/*
				 * time to draw new thing on the screen and start dragging~
				 */
				dragController.startDrag();

				//Toast.makeText(context, String.valueOf("bylem grid"), Toast.LENGTH_SHORT).show();		
				return true;
			}

		});

		// -----------------------------------------------------------------
		
		this.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
			}

			@Override
			public void onScrollStateChanged(AbsListView arg0, int arg1) {
				wasScrolled = true;
			}

		});
		// -----------------------------------------------------------------
		 
		

	}

	/**
	 * 
	 * @return orientation of screen
	 */
	public int getOrientation() {
		return orientation;
	}

	/**
	 * Get position in GridView
	 * 
	 * @return starting point in width of grid for that position
	 */
	private int getOffsetFromPositionX(int pos) {
		int position = pos % 6;
		if (position % 2 == 0) {
			return 0;
		}
		return accountWidth + spacer + 1;
	}

	/**
	 * Function that gives information about offset from top-left corner 
	 * for position of int stored in itemToMovePosition, which indicates
	 * box which was onLongClicked to move
	 * 
	 * @return offset of X
	 */
	public int getOffsetFromSelectedPositionX() {
		int position = itemToMovePosition % 6;
		if (orientation == 2){

			if (position % 2 == 0) {
				return 0;
			}
			return accountWidth + spacer;
		}
		else {

			if (position % 3 == 0) {
				return 0;
			}
			else if (position % 3 == 1){
				return accountWidth + spacer;				
			}
			return 2*accountWidth + 2*spacer;
		}
	}


	/**
	 * Function that gives information about offset from top-left corner 
	 * for position of int stored in itemToMovePosition, which indicates
	 * box which was onLongClicked to move
	 * 
	 * @return offset of Y
	 */
	public int getOffsetFromSelectedPositionY() {
		//int topVisiblePosition = this.getFirstVisiblePosition();
		//Toast.makeText(context, String.valueOf(topVisiblePosition), Toast.LENGTH_SHORT).show();
		//int position = (itemToMovePosition - topVisiblePosition) % 6;
		int position = itemToMovePosition % 6;
		if (orientation == 2){
			position /= 2;
			return ( position )* accountHeight + (position ) * spacer;		
		}
		else {
			position /= 3;		
			return ( position )* accountHeight + (position ) * spacer;				
		}
	}

	/**
	 * Get position in GridView
	 * 
	 * @return starting point in height of grid for that position
	 */
	private int getOffsetFromPositionY(int pos) {
		int position = pos % 6;
		if (position % 2 != 0)
			position--;
		return (position + 2) / 2 * accountHeight;
	}

	/**
	 * Get (x,y) of point in gridView, and number of position of topVisibleItem
	 * of GridView
	 * 
	 * @return position which is at (x,y)
	 */
	private int getPositionFromOffset(int offsetX, int offsetY,
			int topVisibleItem) {
		int mult = 1;
		int tempPosition = topVisibleItem;
		int height = accountHeight + spacer;

		while (mult * height < offsetY) {
			mult++;
			if (orientation == 3)
				tempPosition += 3;
			else
				tempPosition += 2;
		}

		if (offsetX > accountWidth + spacer + accountWidth) {
			tempPosition += 2;
		} else if (offsetX > accountWidth) {
			tempPosition += 1;
		}

		int topVisiblePosition = this.getFirstVisiblePosition();
		tempPosition -= topVisiblePosition;
		
		return tempPosition;
	}

	/**
	 * Set the density of screen.
	 */
	public void setDensity(int d) {
		density = d;
	}

	/**
	 * Get dp to calculate
	 * 
	 * @return value of dp in px with current density value
	 */
	public int dpToPx(int m) {
		// The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160)
		return m * density / 160;
	}

	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction();
		switch(action){
			case MotionEvent.ACTION_DOWN:{
				// do nothing special
				return super.onTouchEvent(event);
			}
			case MotionEvent.ACTION_MOVE:{
				// inform to move
				if (dragController.isDragging()){
					dragController.dragTo( (int) event.getRawX(), (int) event.getRawY()); 
					return true;					
				}
				return super.onTouchEvent(event);
			}
			case MotionEvent.ACTION_UP:{
				// dragging finished
				if (dragController.isDragging()){
					dragController.stopDrag();					
				}
				else if (wasScrolled){
					afterScrollClipping();
				}
				return super.onTouchEvent(event);
			}
		}
		return super.onTouchEvent(event);
	}
	
	/**
	 * After scrolling this function makes smoothscroll to show 6 accounts, 
	 * not 4 full and 4 halfs
	 */
	private void afterScrollClipping(){
		View v = getChildAt(0);
		int top = v.getTop();
		// top -> how many px are out of screen
		// (-1) * halfHeight -> if it is more than half
		if (top > (-1) * halfHeight) {
			smoothScrollBy(top, 100);
		} else {
			smoothScrollBy((accountHeight + top) + spacer, 100);
		}
		wasScrolled = false;
	}
	

	/**
	 * Setting size of GridView and its children. As well as grid proportions.
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = MeasureSpec.getSize(widthMeasureSpec);
		int height = MeasureSpec.getSize(heightMeasureSpec);
		setMeasuredDimension(width, height);
		gridWidth = width;
		gridHeight = height;

		spacer = dpToPx(2);
		if (spacer % 2 != 0) {
			spacer++;
			this.setHorizontalSpacing(spacer);
			this.setVerticalSpacing(spacer);
		}

		if (height > width) {
			height -= (2 * spacer);
			accountHeight = height / 3;
			width -= spacer;
			accountWidth = width / 2;
			orientation = 2;
		} else {
			width -= (2 * spacer);
			accountWidth = width / 3;
			height -= spacer;
			accountHeight = height / 2;
			orientation = 3;
		}
		halfHeight = accountHeight / 2;
		this.setColumnWidth(accountWidth);

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	
	public void changePositions(){
		AccountAdapter adapter = (AccountAdapter) this.getAdapter();
		adapter.changePosition(itemToMovePosition + firstTopPosition, currPosition + firstTopPosition);
	}
	
	public void deletePosition(){
		AccountAdapter adapter = (AccountAdapter) this.getAdapter();
		adapter.deleteAccountAtPosition(itemToMovePosition + firstTopPosition);		
	} 

	/**
	 * height of whole grid
	 */
	private int gridHeight;
	
	/**
	 * width of whole grid
	 */
	private int gridWidth;
	
	/**
	 * height of one child of grid
	 */
	private int accountHeight;

	/**
	 * width of one child of grid
	 */
	private int accountWidth;
	
	/**
	 * half height of account, used when moving
	 */
	private int halfHeight;
	
	/**
	 * number of pixels between childs
	 */
	private int spacer;
	
	/**
	 * actual density of phone screen
	 */
	private int density;
	
	/**
	 * if it is landscape or portrait
	 */
	private int orientation;
	
	/**
	 * if true then account is being moved
	 */
	private boolean inMoveFlag;
	
	/**
	 * if screen was scrolled it is set to true
	 */
	private boolean wasScrolled;

	/**
	 * actual context
	 */
	private Context context;

	/**
	 * position of item which will be moved around
	 */
	private int itemToMovePosition = 1;
	
	/**
	 * Movment of screenshot is done in it
	 */
	private DragFrame dragController;
	
	/**
	 * Previous view above which was dragged view
	 */
	private int oldPosition = 1;

	/**
	 * Actual view above which was dragged view
	 */
	private int currPosition = 1;
	
	/**
	 * First visible position in gridView
	 */
	private int firstTopPosition = 0;
}
